﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Web;

using HtmlAgilityPack;

namespace Penult.BNet.Halo3.PlayedGames
{
    public class PlayedGamesManager
    {
        private static string LinkTemplate = @"http://www.bungie.net/stats/PlayerStatsHalo3.aspx?player={0}&ctl00_mainContent_bnetpgl_recentgamesChangePage={1}";
        private static string GameTemplate = @"http://www.bungie.net/Stats/GameStatsHalo3.aspx?gameid={0}";

        public static List<int> GetGameIDs(string gamertag)
        {
            string encodedGamertag = HttpUtility.UrlEncode(gamertag);
            List<int> foundGameIDs = new List<int>();
            List<int> foundGameIDsOnPage = new List<int>();

            if (string.IsNullOrEmpty(System.Web.HttpContext.Current.Request["i"]))
            {
                int numberOfGames = GetNumberOfPlayedGamePages(gamertag);
                float fractionOfNumberOfPages = numberOfGames / 25;

                int numberOfPages = (int)Math.Ceiling(fractionOfNumberOfPages);

                System.Threading.Parallel.For(1, numberOfPages, i =>
                {
                    Uri link = new Uri(String.Format(LinkTemplate, encodedGamertag, i));

                    foundGameIDsOnPage = GetGameIDsFromLink(link);
                    foundGameIDs.AddRange(foundGameIDsOnPage);
                });
            }
            else
            {
                int i = 1;

                do
                {
                    Uri link = new Uri(String.Format(LinkTemplate, encodedGamertag, i++));

                    foundGameIDsOnPage = GetGameIDsFromLink(link);
                    foundGameIDs.AddRange(foundGameIDsOnPage);
                }
                while (foundGameIDsOnPage.Count > 0);
            }

            return (foundGameIDs);
        }

        private static int GetNumberOfPlayedGamePages(string gamertag)
        {
            string link = string.Format(LinkTemplate, HttpUtility.UrlEncode(gamertag), 1);
            int returnValue = 0;
            HtmlWeb hw = new HtmlWeb();
            HtmlDocument doc = hw.Load(link);

            string path = @"(//*/tr[@class='GridPager_Bungie'])[1]";
            HtmlNodeCollection gridHeaderNodes = doc.DocumentNode.SelectNodes(path);

            if (gridHeaderNodes != null)
            {
                foreach (HtmlNode node in gridHeaderNodes)
                {
                    string text = node.InnerText;

                    Regex regex = new Regex(@"(?<NumberOfGames>[\d]+)\.", RegexOptions.IgnoreCase);

                    Match match = regex.Match(text);

                    Group group = match.Groups["NumberOfGames"];

                    returnValue = Convert.ToInt32(group.Value);
                }
            }

            return (returnValue);
        }

        private static List<int> GetGameIDsFromLink(Uri link)
        {
            List<int> returnValue = new List<int>();
            HtmlWeb hw = new HtmlWeb();
            HtmlDocument doc = hw.Load(link.AbsoluteUri);

            string path = @"//*/table[@class='MasterTable_Bungie']/tbody/tr/td[1]/a";
            HtmlNodeCollection gamesHrefNodes = doc.DocumentNode.SelectNodes(path);

            if (gamesHrefNodes != null)
            {
                foreach (HtmlNode node in gamesHrefNodes)
                {
                    string gameUrl = node.Attributes["href"].Value;

                    int indexOfAmp = gameUrl.IndexOf('&');
                    string removedGameUrl = gameUrl.Remove(indexOfAmp);
                    string substringOfGameUrl = removedGameUrl.Substring(removedGameUrl.IndexOf("=") + 1);

                    int gameId = Convert.ToInt32(substringOfGameUrl);

                    returnValue.Add(gameId);

                    //try
                    //{
                    //    returnValue.Add(GetGame(gameId));

                    //    HttpContext.Current.Response.Write(DateTime.Now.ToString() + " - Game Succeeded - " + gameId + "<br />");
                    //}
                    //catch
                    //{
                    //    HttpContext.Current.Response.Write(DateTime.Now.ToString() + " - <b>Game Failed - " + gameId + "</b><br />");
                    //}

                    //HttpContext.Current.Response.Flush();
                }
            }

            return (returnValue);
        }

        public static Game GetGame(int bnetGameID)
        {
            return (new Game(new Uri(String.Format(GameTemplate, bnetGameID))));
        }


        private static void ThrowPathException(string path)
        {
            throw new ArgumentException("There is no content at the path " + path);
        }
    }
}
